package com.lance.code.synctaskapplication;

import ohos.app.Context;
import ohos.eventhandler.EventHandler;
import ohos.eventhandler.EventRunner;
import ohos.hiviewdfx.HiLog;
import ohos.hiviewdfx.HiLogLabel;

public abstract class OhosAsyncTask {
    protected HiLogLabel LABEL = new HiLogLabel(HiLog.DEBUG, 0, "OhosAsyncTask");
    private Thread thread;
    private Context context;
    private Runnable onMainRunnable;
    private volatile Status mStatus = Status.PENDING;
    private EventHandler eventHandler = new EventHandler(EventRunner.current());

    public OhosAsyncTask(Context context) {
        this.context = context;
    }

    private Runnable onThreadRunnable = new Runnable() {
        @Override
        public void run() {
            if (mStatus != Status.PENDING) {
                switch (mStatus) {
                    case RUNNING:
                        throw new IllegalStateException("Cannot execute task:"
                                + " the task is already running.");
                    case FINISHED:
                        throw new IllegalStateException("Cannot execute task:"
                                + " the task has already been executed "
                                + "(a task can be executed only once)");
                }
            }
            mStatus = Status.RUNNING;
            HiLog.debug(LABEL, "doInBackground() ThreadName:" + Thread.currentThread().getName());
            doInBackground();
            if (mStatus == Status.RUNNING) {
                onMainRunnable = new Runnable() {
                    @Override
                    public void run() {
                        onPostExecute();
                        mStatus = Status.FINISHED;
                    }
                };
                eventHandler.postTask(onMainRunnable);
            }
        }
    };

    protected void onPreExecute() {
        HiLog.debug(LABEL, "onPreExecute() ThreadName:" + Thread.currentThread().getName());
    }

    protected abstract void doInBackground();

    protected void onPostExecute() {
        HiLog.debug(LABEL, "onPostExecute() ThreadName:" + Thread.currentThread().getName());
    }

    public final void execute() {
        if (thread != null) {
            thread.interrupt();
        }

        onPreExecute();
        thread = new Thread(onThreadRunnable);
        thread.start();
    }

    /**
     * Returns the current status of this task.
     *
     * @return The current status.
     */
    public final Status getStatus() {
        return mStatus;
    }

    public final void cancel() {
        HiLog.debug(LABEL, "task cancel");
        mStatus = Status.FINISHED;
        if (thread != null) {
            thread.interrupt();
        }
        if (onMainRunnable != null) {
            eventHandler.removeTask(onMainRunnable);
        }
    }

    /**
     * Indicates the current status of the task. Each status will be set only once
     * during the lifetime of a task.
     */
    public enum Status {
        /**
         * Indicates that the task has not been executed yet.
         */
        PENDING,
        /**
         * Indicates that the task is running.
         */
        RUNNING,
        /**
         * Indicates that {@link OhosAsyncTask#onPostExecute} has finished.
         */
        FINISHED,
    }
}
